<?php

namespace App\Listeners;

use App\Events\UserLearnLimitCheckEvent;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class UserLearnLimitCheckListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param UserLearnLimitCheckEvent $event
     * @return void
     * @throws \RedisException
     */
    public function handle(UserLearnLimitCheckEvent $event)
    {
        /**
         * 封号条件：（满足其一）
         * 1.刷题超过2800道并且正确率低于35%；
         * 2.单日刷题超过3000道；
         */

        /**
         * 入库：刷题次数
         * 不入库：答题次数
         */

        $limitCount = 5000;                 // 总学习阈值
        $limitQuestionRate = 0.38;          // 最低正确率
        $limitCountOfDay = 4000;            // 每日学习阈值

        $defaultValue = [
            'all' => [
                'count' => 0,
                'time' => time()
            ],
            'today' => [
                'count' => 0,
                'time' => time()
            ]
        ];
        $defaultCacheValue = serialize($defaultValue);

        $user = User::find($event->userId);
        if ($user) {
            // 缓存键名
            // $cacheKey = 'user_learn:'.$user->id;
            $fullKey = 'UserLearn';
            $hashKey = 'userId='.$user->id;
            // 获取缓存中的数据
            $cacheValue = Redis::client()->hGet($fullKey, $hashKey);
            if (!$cacheValue) $cacheValue = $defaultCacheValue;

            // 反序列化缓存值
            $cacheValue = unserialize($cacheValue);
            $todayCountInCache = $cacheValue['today']['count'] ? intval($cacheValue['today']['count']) : 0;
            $todayTimeInCache = $cacheValue['today']['time'] ? intval($cacheValue['today']['time']) : time();
            $allCountInCache = $cacheValue['all']['count'] ? intval($cacheValue['all']['count']) : 0;
            // $allTimeInCache = $cacheValue['all']['time'] ? intval($cacheValue['all']['time']) : time();

            // 重置当日数据
            if (Carbon::createFromTimestamp($todayTimeInCache)->isYesterday()) {
                $todayCountInCache = 0;
                $todayTimeInCache = time();
                $cacheValue['today']['count'] = $todayCountInCache;
                $cacheValue['today']['time'] = $todayTimeInCache;
            }

            /**
             * 开始处理判断
             */

            // 判断当日数量
            if (Carbon::createFromTimestamp($todayTimeInCache)->isToday() && $todayCountInCache >= $limitCountOfDay) {
                // 封禁
                $user->status = 'ban';
                $user->save();
                Log::info('[刷题限制机制]用户ID:'.$user->id.'已被封禁，原因：当日刷题次数超过过阈值:'.$limitCountOfDay);
            }

            // 判断全部数量及正确率
            if ($allCountInCache >= $limitCount && $user->status != 'ban') {
                // 获取正确率
                $rate = 0;
                $rightCount = DB::table('qh_user_question_logs')->where('userId', $user->id)->where('result', 1)->count();
                $wrongCount = DB::table('qh_user_question_logs')->where('userId', $user->id)->where('result', 2)->count();

                $sum = $rightCount + $wrongCount;
                if ($sum > 0) {
                    $rate = round($rightCount / $sum, 2);
                }
                if ($rate <= $limitQuestionRate) {
                    // 封禁
                    $user->status = 'ban';
                    $user->save();
                    Log::info('[刷题限制机制]用户ID:'.$user->id.'已被封禁，原因：刷题总数超过过阈值:'.$limitCount.'并且正确率低于阈值:'.$limitQuestionRate);
                }
            }

            // 更新缓存中的数量
            if ($event->mode == 2) {
                $cacheValue['today']['count'] = $todayCountInCache + 1;
                $cacheValue['today']['time'] = time();
                $cacheValue['all']['count'] = $allCountInCache + 1;
            }

            Redis::client()->hSet($fullKey, $hashKey, serialize($cacheValue));
        }
    }
}
